#include "fGfxmath.h"
#include <math.h>

////////////////////////////////////////////////////////////////////////////////
//fShapeBase
fShapeBase::fShapeBase() :iPrecision(10)
{
	iWidth = 0;
	iHeight = 0;
	iA = 0;
	iB = 0;
	iD = 0;
}

fShapeBase::~fShapeBase()
{

}

int fShapeBase::GetPos_Y( int /*a0*/, int /*b0*/ )
{
	return 0;
}

////////////////////////////////////////////////////////////////////////////////
//fParabola
fParabola::fParabola(void)
{
	iA = 0;
	iB = 0;
	iC = 0;
	iD = 0;
	
	iWidth = 0;
	iHeight = 0;
}

fParabola::~fParabola(void)
{
}

void fParabola::Init(int width, int height, int isUp)
{
	if ( 0 == width || 0 == height)
	{
		iA = 0;
		iB = 0;
		iC = 0;
		iD = 0;
	}
	
	iWidth = width;
	iHeight = height;

	if ( isUp == 1)
	{
		iA = 4*height;
		iB = -4*iPrecision*height*width;
		iC = height;
	}
	else
	{
		iA = -4*height;
		iB = 4*iPrecision*height*width;
		iC = 0;
	}
	iD = iPrecision*iPrecision*iWidth*iWidth;	
}

fParabola::fParabola(int width, int height, int isUp)
{
	Init(width,height,isUp);
}

int fParabola::GetPos_Y( int a0, int b0 )
{
	if ( a0 == iWidth)
	{
		return iC;
	}
	int X = a0*iPrecision+b0;

	__int64 nTemp =  (iA*X + iB);
	nTemp *= X;
	__int64 nCount = nTemp / iD;
	__int64 nLeft  = nTemp % iD;
	if ( 2*nLeft > iD)
	{
		nCount++;
	}

	return (int)(nCount + iC);
}

void fParabola::Self()
{
#if 0
	cout<< "iWidth  : " << iWidth << endl
		<< "iHeight : " << iHeight << endl
		<< "iA      : " << iA << endl
		<< "iB      : " << iB << endl
		<< "iC      : " << iC << endl
		<< endl;	
#endif	
}


///////////////////////////////////////////////////////////////////////////////////////
fEllipse::fEllipse()
{
	Init(0,0);
}
fEllipse::fEllipse(int nWidth, int nHeight)
{
	Init( nWidth, nHeight );
}

fEllipse::~fEllipse()
{

}

void fEllipse::Init(int nWidth, int nHeight )
{
	iWidth = nWidth;
	iHeight = nHeight;

	iD = iWidth*iPrecision;
	iA = iD*iD;
	iB = iHeight*iHeight;

	iA0 = iWidth*iWidth;
	iB0 = iHeight*iHeight;
	iD0 = iA0;
	iD0 *= iB0;
}
#define min(a,b) ((( a ) < ( b )) ? ( a ) : ( b ))

int fEllipse::GetPos_Y( int a0, int b0 )
{
	int X = a0 * iPrecision + b0;

	__int64 nTemp = iA-X*X;
	nTemp *= iB;
	
	__int64 nCount = nTemp / iA;
	__int64 nLeft  = nTemp % iA;
	if ( 2*nLeft > iA)
	{
		nCount++;
	}

	nCount = nCount > 0 ? nCount : -nCount;
	//return (int)sqrt((double)nCount);
	int temp_y = (int)sqrt((double)nCount);
	return min( iHeight, temp_y );

}

/*
x = [1/(B+AQ)]*D
y = [Q/(B+AQ)]*D
A0 = w^2
B0 = h^2
D0 = A0*B0
*/
int fEllipse::GetPos(double fAngle, int& nPosX, int& nPosY)
{
	double pi = 3.1415926;
	while (fAngle > 360.00)
	{
		fAngle -= 360.00;
	}
	
	double angle = pi*fAngle/180;
	double a = tan(angle);
	a *=a;
	double b = iB0 + iA0*a;
	__int64 temp = iD0;
	nPosX = (int)sqrt(temp/(double)b);
	nPosY = (int)sqrt((temp*a)/(double)b);
	if ( fAngle > 90.0 && fAngle <= 180.0 )
	{
		nPosX = -nPosX;
	}

	if ( fAngle > 180.0 && fAngle <= 270.0 )
	{
		nPosX = -nPosX;
		nPosY = -nPosY;
	}

	if ( fAngle > 270.0 && fAngle <= 360.0 )
	{
		nPosY = -nPosY;
	}
	return 1;
}
////////////////////////////////////////////////////////////////////////////////////////
//
fHyperbola::fHyperbola(int nWidth, int nHeight)
{
	Init( nWidth, nHeight );
}

fHyperbola::fHyperbola()
{

}
void fHyperbola::Init(int nWidth, int nHeight)
{
	iWidth = nWidth;
	iHeight = nHeight;
	iPos = nWidth/2;

	iA = iHeight*iHeight;
	iB = -iWidth*iWidth*iPrecision*iPrecision;
	iD = -3*iB;
}

int fHyperbola::GetPos_Y(int a0, int b0 )
{
	if ( a0 < iPos)
	{
		return -1;
	}
	int X = a0 * iPrecision + b0;
	__int64 nTemp = 4*X*X+iB;
	nTemp *= iA;

	__int64 nCount = nTemp / iD;
	__int64 nLeft  = nTemp % iD;
	if ( 2*nLeft > iD)
	{
		nCount++;
	}

	nCount = nCount > 0 ? nCount : -nCount;
	return (int)sqrt((double)nCount);
}

fHyperbola::~fHyperbola()
{

}

//////////////////////////////////////////////////////////////////////////
//
